﻿using Essential.Diagnostics;
using RockBus.Logging.Interfaces;
using System;
using System.Diagnostics;
using System.Reflection;
using System.Transactions;

namespace RockBus.Logging.Trace
{
    public class TraceLogger : ILogger
    {
        private static readonly TraceSource _trace = new TraceSource("RockBus");
        private Type _unusedType = typeof(ColoredConsoleTraceListener);

        public void Log(MethodBase currentMethod, MessageData messageData)
        {
            this.Log(
                currentMethod,
                LogLevelEnum.Debug,
                MessageData.Format,
                messageData.MessageEvent,
                messageData.ReceiveAddress,
                messageData.Action,
                messageData.CorrelationId,
                messageData.Text,
                messageData.DestinationAddress);
        }

        public void Log(MethodBase currentMethod, LogData logData)
        {
            switch (logData.LogLevel)
            {
                case LogLevelEnum.Error:
                    this.LogError(currentMethod, logData.Text);
                    break;

                case LogLevelEnum.Warning:
                    this.LogWarning(currentMethod, logData.Text);
                    break;

                case LogLevelEnum.Info:
                    this.LogInfo(currentMethod, logData.Text);
                    break;

                case LogLevelEnum.Debug:
                    this.LogDebug(currentMethod, logData.Text);
                    break;

                case LogLevelEnum.Verbose:
                    this.LogVerbose(currentMethod, logData.Text);
                    break;

                default:
                    break;
            }
        }

        public void Log(MethodBase currentMethod, LogLevelEnum logLevel, string text, params object[] args)
        {
            text = this.FormatLogText(currentMethod, text);

            switch (logLevel)
            {
                case LogLevelEnum.Error:
                    _trace.TraceEvent(TraceEventType.Error, 0, text, args);
                    break;

                case LogLevelEnum.Warning:
                    _trace.TraceEvent(TraceEventType.Warning, 0, text, args);
                    break;

                case LogLevelEnum.Info:
                    _trace.TraceEvent(TraceEventType.Information, 0, text, args);
                    break;

                case LogLevelEnum.Debug:
                case LogLevelEnum.Verbose:
                    _trace.TraceEvent(TraceEventType.Verbose, 0, text, args);
                    break;

                default:
                    break;
            }
        }

        public void Log(MethodBase currentMethod, Exception exc)
        {
            this.LogError(currentMethod, exc.ToString());
        }

        public void LogError(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Error, text, args);
        }

        public void LogWarning(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Warning, text, args);
        }

        public void LogInfo(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Info, text, args);
        }

        public void LogDebug(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Debug, text, args);
        }

        public void LogVerbose(MethodBase currentMethod, string text, params object[] args)
        {
            this.Log(currentMethod, LogLevelEnum.Verbose, text, args);
        }

        public void Log(MethodBase currentMethod, LogLevelEnum logLevel, Transaction transaction)
        {
            if (null == transaction)
            {
                this.Log(currentMethod, logLevel, "Transaction: None");
            }
            else
            {
                this.Log(currentMethod, logLevel, "{0}, {1}, {2}, {3}",
                    transaction.TransactionInformation.CreationTime,
                    transaction.TransactionInformation.LocalIdentifier,
                    transaction.TransactionInformation.DistributedIdentifier,
                    transaction.TransactionInformation.Status);
            }
        }

        private string FormatLogText(MethodBase currentMethod, string text)
        {
            return string.Format("{0}.{1}: {2}", currentMethod.DeclaringType.Name, currentMethod.Name, text);
        }
    }
}